package com.miplus.ccrm.core.service.collect;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.base.MPJBaseServiceImpl;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.miplus.ccrm.common.*;
import com.miplus.ccrm.core.controller.vo.ficase.*;
import com.miplus.ccrm.core.mapper.FiCommissionMapper;
import com.miplus.ccrm.core.mapper.FiCreditcasesHistMapper;
import com.miplus.ccrm.core.mapper.FiDistbatchHistMapper;
import com.miplus.ccrm.core.pojo.*;
import com.miplus.ccrm.core.security.JCommonData;
import com.miplus.ccrm.core.service.ExportService;
import com.miplus.ccrm.core.service.conf.FiDistbatchHistService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

@Slf4j
@Service
public class FiCreditcasesHistServiceImpl extends MPJBaseServiceImpl<FiCreditcasesHistMapper, FiCreditcasesHist>
        implements FiCreditcasesHistService {
    @Resource
    private ExportService exportService;
    @Resource
    private FiImportHistService fiImportHistService;
    @Resource
    private FiCommissionMapper fiCommissionMapper;
    @Resource
    private FiCommisMthssumService commisMthssumService;
    @Resource
    private FiDistbatchHistService fiDistbatchHistService;
    @Resource
    private JCommonData jCommonData;

    @Override
    public IPage<DistHistResVo> fiCaseDistList(JSysUser user, DistHistReqVo paras)
    {//委外分案历史管理
        return baseMapper.quyDistBatchList(new Page<>(paras.getPageNum(), paras.getPageSize()),
                paras,user.getGroups(),user.getUsrid()
        );
    }

    // 委外历史管理-》 批次明细
    @Override
    public IPage<DistHistResVo> fiCaseDistBatchDetailList(FiDistBtcTailReqVo paras)
    {
        return baseMapper.quyDistBatchTailList(new Page<>(paras.getPageNum(), paras.getPageSize()),paras);
    }

    // 委外历史管理-》分案明细
    @Override
    public IPage<FiDistDetailResVo> fiCaseDistDetailList(JSysUser user, FiDistDetailReqVo paras)
    {//出催的回收时间使用出催时间，2024-11-07
        String $usrid=user.getUsrid();
        String usrgrp=user.getGroups();
        //2024-08-18 add and fh.distdt=fc.distdt 条件及fi.repay
        return selectJoinListPage(new Page<>(paras.getPageNum(), paras.getPageSize()),
                FiDistDetailResVo.class,
                new MPJLambdaWrapper<FiCreditcasesHist>()
                        .distinct()
                        .selectAs(FiCreditcasesHist::getCreditcaseid,FiDistDetailResVo::getFicaseid)
                        .selectAs("g.grpname", FiDistDetailResVo::getGrpname)
                        .selectAs("fun_getnames('PUBLIC.MORAUTO',t.distributetype)", FiDistDetailResVo::getDisttypedsc)
                        .selectAs("(case when fh.status is NULL then t.status else fh.status end)", FiDistDetailResVo::getStatus)
                        .selectAs("fun_getnames('COLLECT.STATUS',(case when fh.status is NULL then t.status else fh.status end))", FiDistDetailResVo::getStatusdsc)
                        .selectAs("(case when fh.status=9 then fh.closedt else fh.recycledt end)",FiDistDetailResVo::getRecycledt)
                        .selectAs("fh.mths_odue",FiDistDetailResVo::getRetMthsOdue)
                        .selectAs("fh.odud_prin",FiDistDetailResVo::getRetOdudPrin)
                        .selectAs("fh.over_prin",FiDistDetailResVo::getRetOverPrin)
                        .selectAs("fh.interest_fee",FiDistDetailResVo::getRetInterestFee)
                        .selectAs("fh.penchg_acc",FiDistDetailResVo::getRetPenchgAcc)
                        .selectAs("fh.oth_expense",FiDistDetailResVo::getRetOthExpense)
                        .selectAs("fun_getnames('BUSINESS.TYPE',t.prodtype)", FiDistDetailResVo::getProdtype)
                        .selectAs("(case when fh.status is null then fi.repay else fh.repay end)",FiDistDetailResVo::getRepay)
                        .selectAs("(select dbh.binddays from fi_distbatch_hist dbh where dbh.batchid=t.distbatchid and rownum=1)",FiDistDetailResVo::getBinddays)
                        .leftJoin("fi_creditcases_hist fh on fh.creditcaseid=t.creditcaseid and fh.distbatchid=t.distbatchid and fh.status in(3,4,9) and fh.distdt=t.distdt")
                        .leftJoin("fi_creditcases fi on fi.creditcaseid=t.creditcaseid and fi.distbatchid=t.distbatchid")
                        .leftJoin(SysGrp.class,"g",SysGrp::getGrpid,FiCreditcasesHist::getSendtodept)
                        .select(FiCreditcasesHist::getDistbatchid,FiCreditcasesHist::getDistdt,FiCreditcasesHist::getDistusr,
                                FiCreditcasesHist::getOdudPrin,FiCreditcasesHist::getInterestFee,FiCreditcasesHist::getOthExpense,FiCreditcasesHist::getOverPrin,
                                FiCreditcasesHist::getMthsOdue,FiCreditcasesHist::getPenchgAcc,FiCreditcasesHist::getBindenddt)
                        .eq(FiCreditcasesHist::getStatus,1)
                        .apply("((t.sendtodept={0}) or t.sendtodept in (select mg.grpid from sys_grpmgr mg where mg.grpmanagerid={1}))",usrgrp,$usrid)
                        .apply(JPubUtils.IsNotEmpty(paras.getStatus()),"(case when fh.status is NULL then t.status else fh.status end)={0}",paras.getStatus())
                        .eq(JPubUtils.IsNotEmpty(paras.getProdtype()), FiCreditcasesHist::getProdtype, paras.getProdtype())
                        .eq(JPubUtils.IsNotEmpty(paras.getFicaseid()),FiCreditcasesHist::getCreditcaseid,paras.getFicaseid())
                        .eq(JPubUtils.IsNotEmpty(paras.getDistbatchid()),FiCreditcasesHist::getDistbatchid,paras.getDistbatchid())
                        .eq(JPubUtils.IsNotEmpty(paras.getGrpid()),FiCreditcasesHist::getSendtodept,paras.getGrpid())
                        .between(JPubUtils.IsNotEmpty(paras.getStartdt()), FiCreditcases::getDistdt,JPubUtils.StringToDate(paras.getStartdt()),JPubUtils.StringToDate(paras.getEnddt()))
                        .between(JPubUtils.IsNotEmpty(paras.getRecydt1()), FiCreditcases::getBindenddt,JPubUtils.StringToDate(paras.getRecydt1()),JPubUtils.StringToDate(paras.getRecydt2()))
                        .between(JPubUtils.IsNotEmpty(paras.getReturndt1()), FiCreditcases::getRecycledt,JPubUtils.StringToDate(paras.getReturndt1()),JPubUtils.StringToDate(paras.getReturndt2()))
                        .eq(JPubUtils.IsNotEmpty(paras.getGrptype()),SysGrp::getType,paras.getGrptype())
        );
    }


    @Override
    public CmdResVo saveMthsAsExcel(JSysUser user, CommisReqVo paras, HttpServletResponse response)
    {
        String $usrid=user.getUsrid();
        IPage<CommisResVo> pages=fiCommisMthsList(user, paras);
        ArrayList arr=new ArrayList();

        String exptempid=JPubUtils.getExpTempID(paras.getExpfilename(),"逾期档次结算");
        String filename=JPubUtils.getExpFileName(
                paras.getExpfilename(),exptempid
        );
        pages.convert(u->{
            HashMap map=JPubUtils.toExportMap(u);
            if(map!=null) arr.add(map);
            return u;
        });
        CmdResVo resVo=exportService.ToExcel(
                response,
                arr,
                paras.getExpidlist(),
                paras.getExpnamelist(),
                filename,
                $usrid
        );

        int okcount=resVo.getCount();
        if(okcount>0){
            fiImportHistService.AddExportHist(
                    resVo.getKeyId(),
                    $usrid,
                    exptempid,
                    filename,
                    okcount
            );
        }
        return resVo;
    }

    @Override
    public CmdResVo saveTailAsExcel(JSysUser user, CmsTailReqVo paras, HttpServletResponse response)
    {
        String $usrid=user.getUsrid();
        IPage<CmsTailResVo> pages=fiCommisTailList(user,paras);
        ArrayList arr=new ArrayList();

        String exptempid=JPubUtils.getExpTempID(paras.getExpfilename(),"结算明细");
        String filename=JPubUtils.getExpFileName(
                paras.getExpfilename(),exptempid
        );
        pages.convert(u->{
            HashMap map=JPubUtils.toExportMap(u);
            if(map!=null) arr.add(map);
            return u;
        });
        CmdResVo resVo=exportService.ToExcel(
                response,
                arr,
                paras.getExpidlist(),
                paras.getExpnamelist(),
                filename,
                $usrid
        );

        int okcount=resVo.getCount();
        if(okcount>0){
            fiImportHistService.AddExportHist(
                    resVo.getKeyId(),
                    $usrid,
                    exptempid,
                    filename,
                    okcount
            );
        }

        return resVo;
    }

    @Override
    public IPage<CommisResVo> fiCommisList(JSysUser user, CommisReqVo paras)
    {
        checkBuildCommis(user.getUsrid(),paras,false);
        return baseMapper.quyCommisList(new Page<>(paras.getPageNum(), paras.getPageSize()),paras);
    }

    @Override
    public IPage<CommisResVo> fiCommisMthsList(JSysUser user, CommisReqVo paras)
    {
        checkBuildCommis(user.getUsrid(),paras,true);
        return baseMapper.quyCommisMthsList(new Page<>(paras.getPageNum(), paras.getPageSize()),paras);
    }

    //佣金试算
    @Override
    public IPage<CmsTailResVo> fiCommisTailList(JSysUser user, CmsTailReqVo paras)
    {
        String $usrid=user.getUsrid();
        return baseMapper.quyCommisTailList(new Page<>(paras.getPageNum(), paras.getPageSize()),paras,$usrid);
    }

    private void checkBuildCommis(String usrid, CommisReqVo paras,boolean reset)
    {
        EnumDataStatus dataStatus = jCommonData.getCommissionStatus(paras.getDistbatchid(), paras.getGrpid());
        if (dataStatus == EnumDataStatus.readying || dataStatus == EnumDataStatus.ready) {
            List<FiCommisMthssum> ll = commisMthssumService.getBaseMapper().selectList(new MPJLambdaWrapper<FiCommisMthssum>()
                    .eq(FiCommisMthssum::getDistbatchid, paras.getDistbatchid())
                    .eq(FiCommisMthssum::getGrpid, paras.getGrpid())
                    .ge(FiCommisMthssum::getUpdt,JPubUtils.GetToday())
            );
            if (dataStatus == EnumDataStatus.readying) {
                throw new ServiceException(EnumRCode.DataBuilding.value, EnumRCode.DataBuilding.name);
            }
            else if(JPubUtils.IsEmpty(ll)||reset) {
                buildCommisMthsBase(usrid, paras.getDistbatchid(), paras.getGrpid());
            }
            ll.clear();
        } else if (dataStatus == EnumDataStatus.nready) {
            buildCommisMthsBase(usrid, paras.getDistbatchid(), paras.getGrpid());
        }
    }

    private boolean buildCommisMthsBase(String usrid,String distbatchid,String grpid)
    {//生成逾期档次佣金基础表数据
        List<FiCommission> fiCmsList=fiCommissionMapper.selectList(
                new MPJLambdaWrapper<FiCommission>()
                        .distinct()
                        .eq(FiCommission::getGrpid,grpid)
                        .orderByAsc(FiCommission::getOverdue)
        );
        if(JPubUtils.IsEmpty(fiCmsList)){
            log.warn("buildCommisMthsBase({}).NoFind Commis",grpid);
            throw new ServiceException(EnumRCode.NoSetCommit.value, EnumRCode.NoSetCommit.name);
        }

        Double aimrate=fiDistbatchHistService.getFristAimRate(distbatchid);
        if(JPubUtils.IsEmpty(aimrate)){
            log.warn("buildCommisMthsBase({}).NoFind AimRate",distbatchid);
            throw new ServiceException(EnumRCode.NoSetAimRate.value, EnumRCode.NoSetAimRate.name);
        }

        log.info("buildCommisMthsBase:batchid={},grpid={},aimrate={}",distbatchid,grpid,aimrate);
        jCommonData.setCommissionStatus(
                distbatchid,
                grpid,
                EnumDataStatus.readying,
                1800
        );
        try {
            commisMthssumService.remove(new MPJLambdaWrapper<FiCommisMthssum>()
                    .eq(FiCommisMthssum::getDistbatchid, distbatchid)
                    .eq(FiCommisMthssum::getGrpid, grpid)
            );

            log.info("buildCommisMthsBase({}).Count={}", grpid, fiCmsList.size());
            List<FiCommisMthssum> arrlist = new ArrayList<>();
            for (FiCommission p : fiCmsList) {
                CommisResVo resVo = baseMapper.buildCommisMthsList(distbatchid, grpid, p.getOverdue(), p.getOverdue2(),aimrate);
                if (resVo != null) {
                    FiCommisMthssum mthssum = new FiCommisMthssum();
                    BeanUtils.copyProperties(resVo, mthssum);
                    mthssum.setGrpid(grpid);
                    mthssum.setMthslevel(String.format("M%d-M%d", p.getOverdue(), p.getOverdue2()));
                    mthssum.setUpdt(new Date());
                    mthssum.setUpusr(usrid);
                    arrlist.add(mthssum);
                }
            }
            boolean bret = false;
            if (JPubUtils.IsEmpty(arrlist)) {
                log.warn("buildCommisMthsBase({}).NoFindBaseData", grpid);
                jCommonData.clearCommissionStatus(distbatchid,grpid);
            } else {
                bret = commisMthssumService.saveBatch(arrlist);

                //4小时内有效,为了提高效率，避免频繁刷新
                jCommonData.setCommissionStatus(
                        distbatchid,
                        grpid,
                        EnumDataStatus.ready,
                        14400
                );

                arrlist.clear();
                fiCmsList.clear();
            }
            return bret;
        }
        catch (Exception e){
            log.warn("buildCommisMthsBase:{}",e);
            jCommonData.clearCommissionStatus(distbatchid,grpid);
            throw new ServiceException(EnumRCode.CmdFail.value,e.getMessage());
        }
    }
}